/* 讲解c语言<数据类型>的模块 */

/*引入头文件*/
#include <float.h>/*标准库<浮点数取值范围>*/
#include <limits.h>/*标准库<整数取值范围>*/
#include <stdio.h>/*标准库<输入,输出>*/

/*类型获取*/
void type_obtain()
{
    /* c语言由于历史原因,获取数据类型困难,但 c11 标准引入了解决方案
     * 关键字 _Generic 可以获取数据类型并自定义输出
     * 格式: _Generic(name, type: "output", ...)
     */
    int var = 10;
    printf("var 类型: %s \n", _Generic(var, short: "short", int: "int", long: "long"));
    // 注意: 不要使用不可读的输出,如: int: "123"
}

/*类型转换*/
void type_transformation()
{
    /* c语言截止到c23标准存在两种类型转换
     * 隐式类型转换,强制类型转换
     * 下面会演示两种转换
     */

    // 隐式转换
    // int var = 10;
    // float var_float = var;
    // 不推荐隐式转换,容易引发错误

    // 强制转换
    int var = 10;
    float var_float = (float)var;// int 变量转换 float
    printf("var_float 类型: %s \n", _Generic(var_float, int: "int", float: "float"));
    // 如果结果正确会输出 "var_float 类型: float" ,说明强制类型转换成功了
}

/*常量*/
void type_const()
{
    /* 常量的值<只读>
     * 格式:
     * const type name = number
     */

    // const int var = 10;
    // var = 15;
    // printf("var: %d \n", var);
    // "var = 15;" 改写常量值,引发报错
}

/*字符(char)*/
void type_char()
{
    /* 注意: 字符以"%d"打印会输出"ASCII"码值，"ASCII"码值可以在"c.biancheng.net/c/ascii/"网站查询 */
    char type_char = 'A';
    printf("char: %c, 取值范围: %d ~ %d, 内存占用: %ld \n", type_char, SCHAR_MIN, SCHAR_MAX, sizeof(char));/*sizeof()函数会返回参数的<内存占用>*/
}

/*无符号字符(unsigned char)*/
void type_unsigned_char()
{
    unsigned char type_unsigned_char = 'B';
    printf("unsigned_char: %c, 取值范围: 0 ~ %d, 内存占用: %ld \n", type_unsigned_char, UCHAR_MAX, sizeof(unsigned char));
}

/*短整数(short)*/
void type_short()
{
    short type_short = 32767;
    printf("short: %d, 取值范围: %d ~ %d, 内存占用: %ld \n", type_short, SHRT_MIN, SHRT_MAX, sizeof(short));
}

/*无符号短整数(unsigned short)*/
void type_unsigned_short()
{
    unsigned short type_unsigned_short = 65535;
    printf("unsigned_short: %u, 取值范围: 0 ~ %d, 内存占用: %ld \n", type_unsigned_short, USHRT_MAX, sizeof(unsigned short));
}

/*整数(int)*/
void type_int()
{
    int type_int = 114514;
    printf("int: %d, 取值范围: %d ~ %d, 内存占用: %ld \n", type_int, INT_MIN, INT_MAX, sizeof(int));
}

/*无符号整数(unsigned int)*/
void type_unsigned_int()
{
    unsigned int type_unsigned_int = 1145;
    printf("unsigned_int: %u, 取值范围: 0 ~ %u, 内存占用: %ld \n", type_unsigned_int, UINT_MAX, sizeof(unsigned int));
}

/*长整数(long)*/
void type_long()
{
    /* 注意: 32位系统上long的大小与取值范围会和int相同 */
    long type_long = 233L;/*变量值跟随"L"后缀*/
    printf("long: %ld, 取值范围: %ld ~ %ld, 内存占用: %ld \n", type_long, LONG_MIN, LONG_MAX,  sizeof(long));
}

/*无符号长整数(unsigned long)*/
void type_unsigned_long()
{
    unsigned long type_unsigned_long = 443UL;/*变量值跟随"UL"后缀*/
    printf("unsigned_long: %lu, 取值范围: 0 ~ %lu, 内存占用: %ld \n", type_unsigned_long, ULONG_MAX, sizeof(unsigned long));
}

/*超长整数(long long)*/
void type_long_long()
{
    long long type_long_long = 987LL;/*变量值跟随"LL"后缀*/
    printf("long_long: %lld, 取值范围: %lld ~ %lld, 内存占用: %ld \n", type_long_long, LLONG_MIN, LLONG_MAX, sizeof(long long));
}

/*无符号超长整数(unsigned long long)*/
void type_unsigned_long_long()
{
    /* 注意: 赋值变量时要有"ull"后缀,否则类型报错 */
    unsigned long long type_unsigned_long_long = 963ULL;/*变量值跟随"ULL"后缀*/
    printf("unsigned_long_long: %llu, 取值范围: 0 ~ %llu, 内存占用: %ld \n", type_unsigned_long_long, ULLONG_MAX, sizeof(unsigned long long));

}

/*单精度浮点数(float)*/
void type_float()
{
    /* 注意:
     * "精度"是小数部分精准的位数,比如"float"类型"精度"是6,小数部分有6位准确
     * "%.<number>f"可设置小数显示位数
     */
    float type_float = 3.141592F;/*变量值跟随"F"后缀*/
    printf("float: %.6f, 取值范围: %e ~ %e, 精度: %d, 内存占用: %ld \n", type_float, FLT_MIN, FLT_MAX, FLT_DIG, sizeof(float));
}

/*双精度浮点数(double)*/
void type_double()
{
    double type_double = 3.141592;
    printf("double: %f, 取值范围: %e ~ %e, 精度: %d, 内存占用: %ld \n", type_double, (double)DBL_MIN, (double)DBL_MAX, DBL_DIG, sizeof(double));
    /*(double)类型转换是为了消除ide警告,没有实际作用*/
}

/*布尔数(bool)*/
void type_bool()
{
    /* 注意: bool类型变量赋值0~1以外的数会隐式转换为1 */
    bool type_bool_true = true;/*0是false,1是true*/
    printf("bool: %d, 取值范围: 0 ~ 1, 内存占用: %ld \n", type_bool_true, sizeof(bool));
}

void type_void()
{
    /* 无效类型(void)
     * 内存占用: 无
     * 取值范围: 无
     * 注意: void 用于类型占位,常用于函数定义
     */
}

int main(void)
{
    type_transformation();
}
